﻿using System;
using System.Collections.Generic;

namespace Xiety.DtoGenerator
{
	public class DtoData
	{
		public string FileNamespace { get; set; }
		public List<ClassNode> Classes { get; set; }
		public List<string> Usings { get; set; }

		public DtoData()
		{
			Classes = new List<ClassNode>();
			Usings = new List<string>();
		}

		public void Namespace(string nspace)
		{
			if (nspace == null) throw new ArgumentNullException("nspace");
			this.FileNamespace = nspace;
		}

		public void Using(string name)
		{
			if (name == null) throw new ArgumentNullException("name");
			Usings.Add(name);
		}

		public ClassNode Class(string name, string extends = null, bool abstr = false)
		{
			if (name == null) throw new ArgumentNullException("name");

			var cls = new ClassNode(name, extends, abstr);
			this.Classes.Add(cls);
			return cls;
		}
	}

	public class ClassNode
	{
		public bool Abstract { get; set; }
		public string Extends { get; set; }
		public string Name { get; set; }

		public List<PropertyNode> Properties { get; set; }
		public List<ListPropertyNode> ListProperties { get; set; }
		public List<DependencyPropertyNode> DependencyProperties { get; set; }

		public ClassNode()
		{
			this.Properties = new List<PropertyNode>();
			this.ListProperties = new List<ListPropertyNode>();
			this.DependencyProperties = new List<DependencyPropertyNode>();
		}

		public ClassNode(string name, string extends, bool abstr)
			: this()
		{
			if (name == null) throw new ArgumentNullException("name");

			this.Name = name;
			this.Extends = extends;
			this.Abstract = abstr;
		}

		public ClassNode Property(string type, string name)
		{
			if (type == null) throw new ArgumentNullException("type");
			if (name == null) throw new ArgumentNullException("name");

			var property = new PropertyNode(type, name);
			this.Properties.Add(property);
			return this;
		}

		public ClassNode ListProperty(string type, string name)
		{
			if (type == null) throw new ArgumentNullException("type");
			if (name == null) throw new ArgumentNullException("name");

			var property = new ListPropertyNode(type, name);
			this.ListProperties.Add(property);
			return this;
		}

		public ClassNode DP(string type, string name, object defaultValue = null)
		{
			if (type == null) throw new ArgumentNullException("type");
			if (name == null) throw new ArgumentNullException("name");

			var property = new DependencyPropertyNode(type, name, defaultValue);
			this.DependencyProperties.Add(property);

			return this;
		}
	}

	public class PropertyNode
	{
		public string TypeName { get; set; }
		public string Name { get; set; }

		public PropertyNode(string typeName, string name)
		{
			if (typeName == null) throw new ArgumentNullException("typeName");
			if (name == null) throw new ArgumentNullException("name");

			this.TypeName = typeName;
			this.Name = name;
		}
	}

	public class DependencyPropertyNode
	{
		public string TypeName { get; set; }
		public string Name { get; set; }
		public object DefaultValue { get; set; }

		public string DefaultValueString
		{
			get
			{
				if (DefaultValue is string) return "\"" + DefaultValue + "\"";
				return Convert.ToString(DefaultValue);
			}
		}

		public DependencyPropertyNode(string typeName, string name, object defaultValue)
		{
			if (typeName == null) throw new ArgumentNullException("typeName");
			if (name == null) throw new ArgumentNullException("name");

			this.TypeName = typeName;
			this.Name = name;
			this.DefaultValue = defaultValue;
		}
	}

	public class ListPropertyNode
	{
		public string TypeName { get; set; }
		public string Name { get; set; }

		public ListPropertyNode(string typeName, string name)
		{
			if (typeName == null) throw new ArgumentNullException("typeName");
			if (name == null) throw new ArgumentNullException("name");

			this.TypeName = typeName;
			this.Name = name;
		}
	}
}
